﻿using Callisto.Controls;
using DT.GoogleAnalytics.Metro;
// using DT.GoogleAnalytics.Metro;
using RWSBeeldbank.Common;
using RWSBeeldbank.Data;
using System;
using System.Collections.Generic;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Resources;
using Windows.ApplicationModel.Search;
using Windows.Networking.Connectivity;
using Windows.Storage;
using Windows.UI.ApplicationSettings;
using Windows.UI.Notifications;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Grid App template is documented at http://go.microsoft.com/fwlink/?LinkId=234226

namespace RWSBeeldbank
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton Application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        protected override void OnWindowCreated(WindowCreatedEventArgs args)
        {
            base.OnWindowCreated(args);
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected override async void OnLaunched(LaunchActivatedEventArgs args)
        {
            // clear local cache
            RWSBeeldbank.Utility.Tools.DeleteFilesOlderThenAsync(Constants.FEED_DELETE_CACHE_TIME_DAYS);

            if (args.PreviousExecutionState != ApplicationExecutionState.Running)
            {
                bool loadState = (args.PreviousExecutionState == ApplicationExecutionState.Terminated);
                ExtendedSplash extendedSplash = new ExtendedSplash(args.SplashScreen, loadState);
                Window.Current.Content = extendedSplash;
                Window.Current.Activate();
            }
            
            // Do not repeat app initialization when already running, 
            // just ensure that the window is active
            if (args.PreviousExecutionState == ApplicationExecutionState.Running)
            {
                if (!String.IsNullOrEmpty(args.Arguments))
                {
                    var x = args.Arguments.Split('|');
                    switch (x[0])
                    {
                        case "16" :
                            ((Frame)Window.Current.Content).Navigate(typeof(ItemDetailPage), x[1] + "|" + x[2]);
                            break;
                        case "19":
                            ((Frame)Window.Current.Content).Navigate(typeof(DigitalItemDetailPage), x[1] + "|" + x[2]);
                            break;
                        case "20":
                            ((Frame)Window.Current.Content).Navigate(typeof(VideoDetailPage), x[1] + "|" + x[2]);
                            break;
                    }
                }
                Window.Current.Activate();
                return;
            }

            // Load mediaObject data
            //await MediaObjectDataSource.LoadLocalDataAsync();
            try
            {
                await MediaObjectDataSource.LoadRemoteDataAsync();
            }
            catch(Exception e)
            {
                showMessagebox(e);
            }

            // Register handler for SuggestionsRequested events from the search pane
            //SearchPane.GetForCurrentView().SuggestionsRequested += OnSuggestionsRequested;

            // Register handler for CommandsRequested events from the settings pane
            SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;
            
            #region ActiveTilesAndBadges
            // Clear tiles and badges
            TileUpdateManager.CreateTileUpdaterForApplication().Clear();
            BadgeUpdateManager.CreateBadgeUpdaterForApplication().Clear();
            
            // todo: execute on install
            TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);
            PeriodicUpdateRecurrence recurrence = PeriodicUpdateRecurrence.HalfHour;

            List<Uri> urisToPoll = new List<Uri>();
            urisToPoll.Add(new System.Uri("https://beeldbank.rws.nl/appData/recent_toegevoegde_items.xml"));
            urisToPoll.Add(new System.Uri("https://beeldbank.rws.nl/appData/recent_aangepaste_items.xml"));
            urisToPoll.Add(new System.Uri("https://beeldbank.rws.nl/appData/totale_aantallen_items.xml"));
            urisToPoll.Add(new System.Uri("https://beeldbank.rws.nl/appData/foto_met_hoogste_score.xml"));

            TileUpdateManager.CreateTileUpdaterForApplication().StartPeriodicUpdateBatch(urisToPoll, recurrence);
            BadgeUpdateManager.CreateBadgeUpdaterForApplication().StartPeriodicUpdate(new System.Uri("https://beeldbank.rws.nl/appData/aantal_nieuwe_items.xml"), recurrence);
            #endregion
            
            // Register for push notifications
            var profile = NetworkInformation.GetInternetConnectionProfile();

            // Initialize WindowsStoreProxy.xml
            var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Microsoft\\Windows Store\\ApiData", CreationCollisionOption.OpenIfExists);
            var file = await Package.Current.InstalledLocation.GetFileAsync("Data\\license.xml");
            var newfile = await folder.CreateFileAsync("WindowsStoreProxy.xml", CreationCollisionOption.ReplaceExisting);
            await file.CopyAndReplaceAsync(newfile);

            // Create a Frame to act as the navigation context and associate it with
            // a SuspensionManager key
            var rootFrame = CreateApplicationFrame();
            SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

            if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
            {
                // Restore the saved session state only when appropriate
                await SuspensionManager.RestoreAsync();
            }

            // If the app was closed by the user the last time it ran, and if "Remember
            // "where I was" is enabled, restore the navigation state
            if (args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser)
            {
                if (ApplicationData.Current.RoamingSettings.Values.ContainsKey("Remember"))
                {
                    bool remember = (bool)ApplicationData.Current.RoamingSettings.Values["Remember"];
                    if (remember)
                        await SuspensionManager.RestoreAsync();
                }
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                   
                if (!rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups"))
                {
                    throw new Exception("Failed to create initial page");
                }
            }

            // Place the frame in the current Window and ensure that it is active
            Window.Current.Content = rootFrame;

            // If the app was activated from a secondary tile, show the mediaObject
            if (!String.IsNullOrEmpty(args.Arguments))
            {
                var x = args.Arguments.Split('|');
                switch (x[0])
                {
                    case "16":
                        rootFrame.Navigate(typeof(ItemDetailPage), x[1] + "|" + x[2]);
                        break;
                    case "19":
                        rootFrame.Navigate(typeof(DigitalItemDetailPage), x[1] + "|" + x[2]);
                        break;
                    case "20":
                        rootFrame.Navigate(typeof(VideoDetailPage), x[1] + "|" + x[2]);
                        break;
                }

                Window.Current.Content = rootFrame;
                Window.Current.Activate();
            }
        }

        private async void showMessagebox(Exception exception)
        {
            // Load resource handler
            var resourceLoader = new ResourceLoader();

            // Create the message dialog and set its content
            //var messageDialog = new MessageDialog(resourceLoader.GetString("ErrorNoInternet") + exception.Message + exception.StackTrace);
            var messageDialog = new MessageDialog(resourceLoader.GetString("ErrorNoInternet"));

            // Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
            messageDialog.Commands.Add(new UICommand(resourceLoader.GetString("CloseButton"), new UICommandInvokedHandler(this.CommandInvokedHandler)));

            // Set the command that will be invoked by default
            messageDialog.DefaultCommandIndex = 0;

            // Set the command to be invoked when escape is pressed
            messageDialog.CancelCommandIndex = 1;

            // Show the message dialog
            await messageDialog.ShowAsync();
        }

        private void CommandInvokedHandler(IUICommand command)
        {
            App.Current.Exit();
        }

        private static Frame CreateApplicationFrame()
        {
            var rootFrame = new Frame();

            // Google Analytics helper
            AnalyticsHelper.Setup();

            rootFrame.Navigated += rootFrame_Navigated;
            return rootFrame;
        }

        static void rootFrame_Navigated(object sender, NavigationEventArgs e)
        {
            if (e.Uri == null)
            {
                if (e.SourcePageType != null)
                {
                    string uri = "/" + e.SourcePageType.FullName;
                    AnalyticsHelper.TrackPageView(uri);
                }
            }
            else
            {
                AnalyticsHelper.TrackPageView(e.Uri.ToString());
            }
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private async void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            await SuspensionManager.SaveAsync();
            deferral.Complete();
        }

        /// <summary>
        /// Invoked when the application is activated to display search results.
        /// </summary>
        /// <param name="args">Details about the activation request.</param>
        protected async override void OnSearchActivated(Windows.ApplicationModel.Activation.SearchActivatedEventArgs args)
        {
            // Reinitialize the app if a new instance was launched for search
            if (args.PreviousExecutionState == ApplicationExecutionState.NotRunning ||
                args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser ||
                args.PreviousExecutionState == ApplicationExecutionState.Terminated)
            {
                // Load mediaObject data
                await MediaObjectDataSource.LoadRemoteDataAsync();

                // Register handler for SuggestionsRequested events from the search pane
                SearchPane.GetForCurrentView().SuggestionsRequested += OnSuggestionsRequested;

                // Register handler for CommandsRequested events from the settings pane
                SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;

                // Add a Frame control to the window
                var rootFrame = CreateApplicationFrame();
                SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
                Window.Current.Content = rootFrame;
            }

            SearchResults.Activate(args.QueryText, args.PreviousExecutionState);
        }

        void OnSuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
        {
            string query = args.QueryText.ToLower();

            string[] terms = MediaObjectDataSource.AllKeywords;

            foreach (var term in terms)
            {
                if (term.StartsWith(query))
                    args.Request.SearchSuggestionCollection.AppendQuerySuggestion(term);
            }
        }

        void OnCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
        {
            // Load resource handler
            var resourceLoader = new ResourceLoader();

            // Add an About command
            var about = new SettingsCommand("about", "Info", (handler) =>
            {
                var settings = new Callisto.Controls.SettingsFlyout();
                settings.Content = new AboutUserControl();
                settings.ContentBackgroundBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.ContentForegroundBrush = new SolidColorBrush(Constants.SETTINGS_FOREGROUND);
                settings.HeaderBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.Background = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.HeaderText = "Info";
                settings.FlyoutWidth = Callisto.Controls.SettingsFlyout.SettingsFlyoutWidth.Wide;
                settings.IsOpen = true;
            });

            args.Request.ApplicationCommands.Add(about);

            // Add a Preferences command
            var preferences = new SettingsCommand("preferences", resourceLoader.GetString("PrefSettings"), (handler) =>
            {
                var settings = new Callisto.Controls.SettingsFlyout();
                settings.Content = new PreferencesUserControl();
                settings.ContentBackgroundBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.ContentForegroundBrush = new SolidColorBrush(Constants.SETTINGS_FOREGROUND);
                settings.HeaderBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.Background = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.HeaderText = resourceLoader.GetString("PrefSettings");
                settings.FlyoutWidth = Callisto.Controls.SettingsFlyout.SettingsFlyoutWidth.Narrow;
                settings.IsOpen = true;
            });

            args.Request.ApplicationCommands.Add(preferences);


            // Add a Usage command
            var usage = new SettingsCommand("usage", resourceLoader.GetString("PrefUsage"), (handler) =>
            {
                var settings = new Callisto.Controls.SettingsFlyout();
                settings.Content = new UsageUserControl();
                settings.ContentBackgroundBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.ContentForegroundBrush = new SolidColorBrush(Constants.SETTINGS_FOREGROUND);
                settings.HeaderBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.Background = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.HeaderText = resourceLoader.GetString("PrefUsage");
                settings.FlyoutWidth = Callisto.Controls.SettingsFlyout.SettingsFlyoutWidth.Wide;
                settings.IsOpen = true;
            });

            args.Request.ApplicationCommands.Add(usage);


            // Add a privacy command
            var privacy = new SettingsCommand("privacy", resourceLoader.GetString("PrefPrivacy"), (handler) =>
            {
                var settings = new Callisto.Controls.SettingsFlyout();
                settings.Content = new PrivacyUserControl();
                settings.ContentBackgroundBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.ContentForegroundBrush = new SolidColorBrush(Constants.SETTINGS_FOREGROUND);
                settings.HeaderBrush = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.Background = new SolidColorBrush(Constants.SETTINGS_BACKGROUND);
                settings.HeaderText = resourceLoader.GetString("PrefPrivacy");
                settings.FlyoutWidth = Callisto.Controls.SettingsFlyout.SettingsFlyoutWidth.Wide;
                settings.IsOpen = true;
            });

            args.Request.ApplicationCommands.Add(privacy);

        }

    }
}
